<script setup lang="ts">
import type { Ref } from 'vue';

import type {
  RasterDataSource,
  RasterServiceData,
  VectorDataSource,
  VectorServiceData,
} from './index';

import { computed, onMounted, reactive, ref, watch } from 'vue';

import { BiPin } from '@vben/icons';

import { StorageManager } from '@vben-core/shared/cache';

// ElConfigProvider 组件
import {
  ElButton,
  ElConfigProvider,
  ElIcon,
  ElInput,
  ElOption,
  ElPagination,
  ElRow,
  ElSelect,
  ElTable,
  ElTableColumn,
  ElTag,
} from 'element-plus';
// 引入中文包
import zhCn from 'element-plus/dist/locale/zh-cn.mjs';

import { rasterServiceApi, vectorServiceApi } from '#/api';
import { loadingSvg } from '#/assets/style';
import { useClickOutside } from '#/hooks';

const emit = defineEmits(['beforeAddToLayer', 'closePanel']);

const storageManager = new StorageManager({
  prefix: '',
  storageType: 'sessionStorage',
});

const serviceDataPanelRef: Ref<HTMLElement | null> = ref(null);
const serviceDataType = ref('vector');
const serviceDataTypeList = ref<any>([
  {
    id: 1,
    label: '矢量服务资源',
    value: 'vector',
  },
  {
    id: 2,
    label: '栅格服务资源',
    value: 'raster',
  },
]);
const keyword = ref('');
const isLoading = ref(false);
const emptyText = ref('加载中...');
const userId = storageManager.getItem<string>('userId') as string;
const searchServiceData = ref('');
const currentPage = ref(1);
const pageSize = ref(8);
const totalDataCount = ref(0);
const isPanelFixed = ref(false);
const serviceData = reactive({
  data: [] as RasterServiceData[] | VectorServiceData[],
});

const getServiceData = async () => {
  isLoading.value = true;
  if (serviceDataType.value === 'vector') {
    const { body, count } = await vectorServiceApi.getVectorSList(
      userId,
      pageSize.value,
      currentPage.value,
      keyword.value,
    );
    setTimeout(() => {
      isLoading.value = false;
      // serviceData.data = res.data; // 将响应数据赋值给变量
      serviceData.data = body.map((item: any) => {
        const { id, name, type, geoType, publisher, url, ptName, bbox } = item;
        return {
          id,
          name,
          sourceType: type,
          geoType,
          user: publisher,
          url,
          ptName,
          bbox,
        };
      });
      totalDataCount.value = count;
      if (!totalDataCount.value) emptyText.value = '空空如也';
    }, 500);
  } else {
    const { body, count } = await rasterServiceApi.getRasterSList(
      userId,
      pageSize.value,
      currentPage.value,
      keyword.value,
    );
    setTimeout(() => {
      isLoading.value = false;
      serviceData.data = body.map((item: any) => {
        const { id, name, type, publisher, url, bbox, oriFileId } = item;
        return {
          id,
          name,
          type,
          user: publisher,
          url,
          bbox,
          fileType: oriFileId ? 'tif' : url.split('.').pop(),
        };
      });
      totalDataCount.value = count;
      if (!totalDataCount.value) emptyText.value = '空空如也';
    }, 500);
  }
};
const handleServiceTypeChange = (_val: any) => {
  if (currentPage.value !== 1) currentPage.value = 1;
  serviceData.data = [];
  getServiceData();
};

const filterTableData = computed(() =>
  serviceData.data.filter(
    (data: any) =>
      !searchServiceData.value ||
      data.name.toLowerCase().includes(searchServiceData.value.toLowerCase()),
  ),
);
watch(filterTableData, (newVal) => {
  if (searchServiceData.value && newVal.length === 0)
    emptyText.value = '找不到您想要的资源';
});
const filterTag1 = (
  value: string,
  row: RasterServiceData | VectorServiceData,
) => {
  return 'geoType' in row ? row.geoType === value : row.fileType === value;
};
const filterTag2 = (
  value: string,
  row: RasterServiceData | VectorServiceData,
) => {
  if (serviceDataType.value === 'vector') {
    if ('sourceType' in row) {
      return row.sourceType === value;
    }
  } else {
    if ('type' in row) {
      return row.type === value;
    }
  }
};

const getGeoType = (value: string) => {
  switch (value) {
    case 'LINESTRING':
    case 'MULTILINESTRING': {
      return '线';
    }
    case 'MULTIPOINT':
    case 'POINT': {
      return '点';
    }
    case 'MULTIPOLYGON':
    case 'POLYGON': {
      return '面';
    }
    default: {
      return '未知';
    }
  }
};
const getFileType = (value: string) => {
  switch (value) {
    case 'jpg': {
      return 'jpg';
    }
    case 'png': {
      return 'png';
    }
    case 'tif':
    case 'tiff': {
      return 'tif';
    }
    default: {
      return '未知';
    }
  }
};
const getType = (value: string) => {
  switch (value) {
    case 'geojson': {
      return 'GeoJSON';
    }
    case 'image': {
      return 'Image';
    }
    case 'tiles': {
      return 'Tiles';
    }
    case 'vector': {
      return 'MVT';
    }
    case 'wms': {
      return 'WMS';
    }
  }
};
const getColorType = (value: string) => {
  switch (value) {
    case 'jpg':
    case 'MULTIPOLYGON':
    case 'POLYGON': {
      return 'primary';
    }
    case 'LINESTRING':
    case 'MULTILINESTRING':
    case 'png': {
      return 'warning';
    }
    case 'MULTIPOINT':
    case 'POINT':
    case 'tif': {
      return 'success';
    }
    default: {
      return 'info';
    }
  }
};

const handleCurrentPageChange = (_val: number) => {
  getServiceData();
};

const handleSizeChange = (_val: number) => {
  getServiceData();
};

const handleClosePanel = () => {
  emit('closePanel');
};
const { handler } = useClickOutside(serviceDataPanelRef, handleClosePanel);
const addToLayer = (source: RasterServiceData | VectorServiceData) => {
  let dataSource = {} as RasterDataSource | VectorDataSource;
  if (serviceDataType.value === 'vector' && 'sourceType' in source) {
    dataSource = {
      sourceId: source.id,
      sourceName: source.name,
      sourceType: source.sourceType,
      geoType: source.geoType,
      user: source.user,
      url: source.url,
      ptName: source.ptName,
      bbox: source.bbox,
    };
  } else if (serviceDataType.value === 'raster' && 'type' in source) {
    dataSource = {
      sourceId: source.id,
      sourceName: source.name,
      sourceType: source.type,
      fileType: source.fileType,
      user: source.user,
      url: source.url,
      bbox: source.bbox,
    };
  }
  emit('beforeAddToLayer', dataSource, isPanelFixed.value);
};

const toggleFixPanel = () => {
  isPanelFixed.value = !isPanelFixed.value;
  if (isPanelFixed.value) {
    document.removeEventListener('click', handler);
  } else {
    document.addEventListener('click', handler);
  }
};

onMounted(() => {
  getServiceData();
});
</script>

<template>
  <div ref="serviceDataPanelRef">
    <ElRow type="flex" align="middle">
      <div class="pop-header">
        <h3 class="font-semibold text-gray-500">服务资源类型:&nbsp;</h3>
        <ElSelect
          v-model="serviceDataType"
          placeholder="请选择"
          style="width: 65%; height: 100%"
          @change="handleServiceTypeChange"
        >
          <ElOption
            v-for="item in serviceDataTypeList"
            :key="item.id"
            :label="item.label"
            :value="item.value"
          />
        </ElSelect>
        <div
          class="close-btn-box"
          @click="toggleFixPanel"
          :title="isPanelFixed ? '取消固定' : '固定'"
        >
          <ElIcon
            size="18"
            class="close-btn"
            :class="{ unfixed: !isPanelFixed }"
          >
            <BiPin />
          </ElIcon>
        </div>
      </div>
    </ElRow>
    <!-- 汉化 -->
    <ElConfigProvider :locale="zhCn">
      <!-- <el-config-provider> -->
      <ElTable
        size="small"
        :data="filterTableData"
        height="31vh"
        highlight-current-row
        :empty-text="emptyText"
        v-loading="isLoading"
        element-loading-text="获取中..."
        :element-loading-svg="loadingSvg"
        element-loading-svg-view-box="0, 0, 20, 20"
      >
        <ElTableColumn
          prop="name"
          width="160"
          show-overflow-tooltip
          label="资源名称"
        />
        <ElTableColumn
          v-if="serviceDataType === 'vector'"
          prop="geoType"
          label="几何类型"
          width="80"
          :filters="[
            { text: '点', value: 'POINT' },
            { text: '线', value: 'MULTILINESTRING' },
            { text: '面', value: 'MULTIPOLYGON' },
          ]"
          :filter-method="filterTag1"
          filter-placement="bottom-end"
        >
          <template #default="scope">
            <ElTag
              v-if="filterTableData.length > 0"
              :type="getColorType(scope.row.geoType)"
            >
              {{ getGeoType(scope.row.geoType) }}
            </ElTag>
          </template>
        </ElTableColumn>
        <ElTableColumn
          v-else
          prop="fileType"
          label="文件类型"
          width="80"
          :filters="[
            { text: 'tif', value: 'tif' },
            { text: 'png', value: 'png' },
            { text: 'jpg', value: 'jpg' },
          ]"
          :filter-method="filterTag1"
          filter-placement="bottom-end"
        >
          <template #default="scope">
            <ElTag
              v-if="filterTableData.length > 0"
              :type="getColorType(scope.row.fileType)"
            >
              {{ getFileType(scope.row.fileType) }}
            </ElTag>
          </template>
        </ElTableColumn>
        <ElTableColumn
          v-if="serviceDataType === 'vector'"
          prop="sourceType"
          label="类型"
          width="79"
          :filters="[
            { text: 'MVT', value: 'vector' },
            { text: 'GeoJSON', value: 'geojson' },
          ]"
          :filter-method="filterTag2"
          filter-placement="bottom-end"
        >
          <template #default="scope">
            <ElTag
              :type="scope.row.sourceType === 'vector' ? 'success' : 'warning'"
              disable-transitions
            >
              {{ getType(scope.row.sourceType) }}
            </ElTag>
          </template>
        </ElTableColumn>
        <ElTableColumn
          v-else
          prop="type"
          label="类型"
          width="79"
          :filters="[
            { text: 'Image', value: 'image' },
            { text: 'WMS', value: 'wms' },
          ]"
          :filter-method="filterTag2"
          filter-placement="bottom-end"
        >
          <template #default="scope">
            <ElTag
              :type="scope.row.type === 'image' ? 'success' : 'warning'"
              disable-transitions
            >
              {{ getType(scope.row.type) }}
            </ElTag>
          </template>
        </ElTableColumn>
        <ElTableColumn align="right">
          <template #header>
            <ElInput
              v-model="searchServiceData"
              size="small"
              placeholder="搜索资源"
            />
          </template>
          <template #default="scope">
            <ElButton
              size="small"
              type="primary"
              @click="addToLayer(scope.row)"
            >
              添加
            </ElButton>
          </template>
        </ElTableColumn>
      </ElTable>
      <div class="page-box">
        <ElPagination
          small
          @current-change="handleCurrentPageChange"
          @size-change="handleSizeChange"
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="[8, 16, 24]"
          layout="sizes, prev, pager, next, total"
          :total="totalDataCount"
        />
      </div>
    </ElConfigProvider>
  </div>
</template>

<style lang="scss" scoped>
.pop-header {
  display: flex;
  align-items: center;
  width: 100%;

  /* margin-bottom: 10px; */
  padding: 4px 0 5px 10px;
}

:deep(.pop-header .el-select__wrapper) {
  height: 40px;
  font-size: 13px;
}

.close-btn-box {
  position: relative;
  box-sizing: border-box;
  width: 30px;
  height: 30px;
  margin-left: 10px;

  &:hover {
    font-weight: 700;
    color: rgb(63 158 255);
    cursor: pointer;
    border: 1px solid rgb(63 158 255);
    transform: scale(1.05);
  }

  &:has(.close-btn:not(.unfixed)) {
    font-weight: 700;
    color: rgb(63 158 255);
    border: 1px solid rgb(63 158 255);
  }

  .close-btn {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }

  .unfixed {
    transform: translate(-50%, -50%) rotate(45deg);
  }
}

// .icon {
//   width: 1em;
//   height: 1em;
//   /* vertical-align: -0.15em; */
//   fill: currentColor;
//   overflow: hidden;
// }

.page-box {
  display: flex;
  justify-content: center;
  margin: 3px 0;
}

:deep(.el-pagination--small .el-select .el-input) {
  width: 77px;
}
</style>
